/** ***********************************************************************************
* @file         net_task.h
* @brief        网络数据处理任务 头文件
* @details      主要用来处理基础网络数据
* @author       杨小珛
* @date         2020/12/23
* @copyright    北京高知科技有限公司    
* @version      V1.0
* @attention    无
**************************************************************************************/
#ifndef NET_TASK_H
#define NET_TASK_H
/* Standard includes. */
#include "os_app.h"

typedef uint32_t (*socket_recv_fun_t)(uint32_t index, uint8_t* data, uint32_t len);
typedef void (*socket_state_fun_t) (void * arg);

typedef uint8_t gsm_module_start_s;//GSM电源启动状态
typedef uint8_t socket_rev_buf_t;   

#define NER_REG_ERROR_TIME_OUT     ( 200 ) /*网络注册失败等待时间为5分钟，60/3(消息队列阻塞时间为3S) * 10 */

#define NET_DATA_RECV               ( 1 )
#define NET_DATA_SEND               ( 2 )

#define GSM_START_SUC               ( 1 )
#define GSM_RESET_SUC               ( 2 )

#define MAX_IP_LEN                  ( 64 )
#define MAX_SOCKET_CONN_NUM        ( 6 ) /*支持最大的创建网络连接数 从0开始算 0 1 2 3 4 5 */

#define NET_DATA_SEND_OK            ( 1 )
#define NET_DATA_SEND_ERROR         ( 0 )

#define NET_DATA_RECV_OK            ( 1 )
#define NET_DATA_RECV_ERROR         ( 0 )

/***********************SOCKET 检测状态结构体****************************/
#define SOCKET_SELECT_TIME_S       ( 1 )
#define SOCKET_SELECT_TIME_US       ( 10 )
typedef enum
{
    SOCKET_ST_INIT =0,
    SOCKET_REV_OK,
    SOCKET_REV_ERR,
    SOCKET_SEL_OUT,
    SOCKET_SEL_ERR,
    SOCKET_NET_ERR,
}socket_status_e;

typedef enum
{
    SEND_NET_INIT =0,
    SEND_NET_OK,
    SEND_NET_ERR,
}send_net_status_e;

/***********************GPRS 网络注册状态机构体****************************/
typedef enum
{
    SOCKET_STATE_INIT =0,

    SOCKET_SEND_OK,         //< 发送数据正确 
    SOCKET_SEND_ERROR,      //< 发送数据错误
    
    SOCKET_RECV_OK,         //< 发送数据正确
    SOCKET_RECV_ERROR,      //< 发送数据异常
    
    SOCKET_LINK_ERROR,      //< 网络连接异常
    
    SOCKET_CSQ_ERROR,       //< 网络信号异常 
    
    SOCKET_REG_ERROR,       //< 注册GPRS网络异常

    GSM_NET_SLEEP,          //< GSM网络模块进入休眠
    GSM_NET_STOP,           //< GSM网络模块进入停止
    GSM_NET_RST,            //< GSM网络模块需要复位
    GSM_NET_RUN,            //< GSM网络模块运行中
}network_status_e;

typedef struct
{   
    network_status_e net_state;     /*网络状态*/
    uint8_t index_id;               /*网络注册索引号*/
    uint32_t attr_data;             /* 属性数据 */      
}socket_net_state_s;


/*********************NET 连接的网络属性 枚举类型************************/
typedef enum
{
    e_socket_protocol_init = 0,
    e_socket_protocol_tcp ,
    e_socket_protocol_udp ,
    e_socket_protocol_mqtt,
    e_socket_protocol_ssl,
}protocol_type_e;

/*********************GPRS模块SOCKET连接句柄*******************************/
typedef struct
{
    volatile uint8_t             connIndex;             ///< 底层维护, 连接索引号 0-5 = 6 无效,连接成功后,
    volatile uint32_t            scoketId;              ///< 网络创建ID
    volatile protocol_type_e     protocolType;          ///< 顶层维护, SOCKET连接的类型,0:TCP 1:UDP,
    volatile uint16_t            port;                  ///< 顶层维护, 端口号,
    volatile uint8_t             ip[MAX_IP_LEN];        ///< 顶层维护, IP或域名地址,
    volatile uint32_t            connStaus;             ///< 顶底维护, 当前连接的状态 1:连接 0:断开 
    volatile socket_state_fun_t  fDiscCallback;         ///< 顶层维护, 连接断开时底层调用的勾子
    volatile uint32_t            sendTotalBytes;        ///< 发送的数据总数
    volatile uint32_t            recvTotalBytes;        ///< 接收的数据总数
}socket_handle_s;

/*********************NET 连接的网络属性 枚举类型************************/
typedef struct
{   
    uint32_t socket_id;  /*网络注册索引号*/
    uint8_t *task_name;  /*任务的名称*/
    uint8_t *mem_p;       /*动态分配的系统内存*/        
}socket_recv_task_par_s;

/********************GPRS模块SOCKET连接句柄*******************************/
typedef struct
{
    volatile uint8_t  socket_create_num; /*网络创建的数量*/
    volatile socket_handle_s  socket_handle_table[MAX_SOCKET_CONN_NUM];
    volatile GaozQueueHandle_t  socket_recv_table[MAX_SOCKET_CONN_NUM];
}socket_bmt_s;

#define NET_SEND_QUEUE_BLOCK_TIME   ( 3000 )
#define NET_SEND_DATA_RUN_WAIT_TIME   ( 3000 )
#define NET_SEND_DATA_STOP_WAIT_TIME   ( 100 )

#define NET_SEND_DATA_LEN  ( 2048 )
#define NET_RECV_DATA_LEN  ( 2048 )

#define NET_SEND_DATA_QUEUE_DEPTH  ( 20 )
#define NET_REV_DATA_QUEUE_DEPTH  ( 20 )

/********************GPRS发送消息数据结构*************************************/
typedef struct
{
    volatile uint8_t            *pData;             // 数据指针
    volatile uint32_t            MsgIndex;          // 消息类型
    volatile uint32_t            MsgValidUntil;     // 消息有效至时间 tick单位
    volatile uint32_t            DateLen;           // 数据长度
} net_send_data_s,net_rev_data_s;

/****************************创建SOCKET 连接后的状态**************************/
typedef enum
{
	SOCKET_LINK_CREATE_ERROR =0x00,     /* 网络连接未创建  */
	SOCKET_LINK_CREATE_OK,               /* 网络连接创建成功 */
}create_socket_state_e;

/*************************网络运行过程中产生的状态信息***************************/
/*发送数据状态*/
#define	SEND_OK         ( 0x01 )
#define	SEND_ERR        ( 0x02 )

/*接收数据状态*/
#define	RECV_OK         ( 0x01 )
#define	RECV_ERR        ( 0x02 )

/*链接网络状态*/
#define	LINK_OK         ( 0x00 )
#define	LINK_ERR        ( 0x01 )

/*信号质量状态*/
#define	CSQ_OK          ( 0x00 )
#define	CSQ_ERR         ( 0x01 )

/*注册网络状态*/
#define	REG_OK          ( 0x00 )
#define	REG_ERR         ( 0x01 )

/*模块运行状态*/
#define	NET_SLEEP 		( 0x01 )
#define	NET_STOP 		( 0x02 )
#define	NET_RST 		( 0x03 )
#define	NET_RUN 		( 0x04 )

typedef struct
{
	volatile uint8_t send_st; //> 发送数据状态 0 初始化状态 1 发送成功 2 发送失败
	volatile uint8_t recv_st; //> 接收数据状态 0 初始化状态 1 接收成功 2 接收失败
	volatile uint8_t link_st; //> 链接网络状态 0 网络状态正常 1 网络状态异常
	volatile uint8_t csq_st;  //> 信号质量状态 0 信号质量正常 1 信号质量异常
	volatile uint8_t reg_st;  //> 注册网络状态 0 注册网络状态正常 1 注册网络状态异常
	volatile uint8_t net_st;  //> 模块运行状态 0 初始化状态 1 模块进入休眠状态 2 模块进入停止模式 3 模块进入复位模式 4 模块运行正常

}network_run_state_t;

typedef struct
{
	create_socket_state_e 	create_socket_state;	// 创建网络链接的状态
	network_run_state_t 	network_run_state;		// 网络运行过程中的状态
}socket_state_t;

/*************************网络数据接收任务参数结构体***************************/
typedef struct
{
	volatile uint8_t 	index;	// 网络创建的节点
	volatile uint8_t 	*buf;	// 网络数据接收BUF
	volatile char    *name;  // 网络数据接收任务的名称
}socket_recv_para_t;

/******************外部声明结构体全局变量**************************************/
extern GaozQueueHandle_t net_send_data_queue;       /*定义网络发送数据消息队列*/
extern GaozMutexHandle_t net_link_mutex;            /*定义网络连接互斥体*/
extern socket_bmt_s socket_bmt;                     /*定义网络注册网络句柄*/
extern net_send_data_s net_send_msg;                /*定位网络数据接收结构体*/
extern net_rev_data_s net_rev_msg;                  /*GPRS接收数据机构体*/
extern socket_recv_fun_t socket_recv_fun;
extern socket_state_fun_t socket_state_fun;


/** ****************************************************************************
* @remarks       void net_data_create_task( unsigned portBASE_TYPE uxPriority )
* @brief         创建网络连接处理任务
* @param[in]     uxPriority 优先级
* @param[out]    无
* @return        无
* @attention     在系统启动后进行创建
*******************************************************************************/
extern void net_data_create_task( unsigned portBASE_TYPE uxPriority );

/** ****************************************************************************
* @remarks       uint32_t net_send_data_queue_get(net_send_data_s *gprs_msg, uint32_t time_out )
* @brief         获取网络数据发送消息队列数据
* @param[in]     *gprs_msg 获取的数据地址
* @param[out]    无
* @return        pdPASS 接收到数据 pdFAIL 未接收到数据
* @attention     必须在任务中运行
*******************************************************************************/
extern uint32_t net_send_data_queue_get(net_send_data_s *gprs_msg, uint32_t time_out );

/** ****************************************************************************
* @remarks       uint32_t net_connect( char *ip, uint16_t port, uint8_t protocol_type, uint8_t *con_index, uint8_t *conn_staus, uint32_t *con_socketid , uint32_t ip_type)
* @brief         连接GPRS网络
* @param[in]    *ip IP地址 
* @param[in]     port 端口号 
* @param[in]     ip_type 连接类型
* @param[out]    *con_index 连接索引号
* @param[out]    *conn_staus 连接状态
* @param[out]    *con_socketid 网络ID号
* @return        pdFAIL 链接失败 pdPASS 链接成功
* @attention     无
*******************************************************************************/
extern uint32_t net_connect( char *ip, uint16_t port, uint8_t protocol_type, uint8_t *con_index, uint8_t *conn_staus, uint32_t *con_socketid , uint32_t ip_type);

/** ****************************************************************************
* @remarks       uint32_t net_close(uint16_t index ,uint8_t type)
* @brief         关闭NET 网络链接
* @param[in]     index 网络节点
* @param[in]     type 网络连接模式
* @param[out]    无
* @return        pdFAIL 发送失败 pdPASS 发送成功
* @attention     无
*******************************************************************************/
extern uint32_t net_close(uint16_t index ,uint8_t type);

/** ****************************************************************************
* @remarks       void net_socket_state_callback_set( socket_handle_s *pxSocketHandle )
* @brief         设置网络状态回调函数
* @param[in]     *pxSocketHandle 网络套接字
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern void net_socket_state_callback_set( socket_handle_s *pxSocketHandle );

/** ****************************************************************************
* @remarks       void net_recv_data_callback_set( socket_recv_fun_t  fun )
* @brief         设置网络数据接收回调函数
* @param[in]     fun API 函数地址
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern void net_recv_data_callback_set( socket_recv_fun_t  fun );

/** ****************************************************************************
* @remarks       void socket_net_state_callback_set( socket_state_fun_t  fun )
* @brief         设置网络状态回调函数
* @param[in]     fun API 函数地址
* @param[out]    无
* @return        无
* @attention     无
*******************************************************************************/
extern void socket_net_state_callback_set( socket_state_fun_t  fun );

/** ****************************************************************************
* @remarks       uint32_t net_send_data( uint16_t index ,uint8_t * data , uint16_t len )
* @brief         发送GPRS 数据
* @param[in]     index 网络节点
* @param[in]     * data 发送的数据地址
* @param[in]      len 发送的数据长度
* @param[out]    无
* @return        pdFAIL 发送失败 pdPASS 发送成功
* @attention     无
*******************************************************************************/
extern uint32_t net_send_data( uint16_t index ,uint8_t * data , uint16_t len );

/** ****************************************************************************
* @remarks       uint32_t net_free_send_data( uint16_t sock_id ,uint8_t * data , uint16_t len )
* @brief         发送GPRS 数据，无节点维护
* @param[in]     sock_id 网络节点
* @param[in]     * data 发送的数据地址
* @param[in]      len 发送的数据长度
* @param[out]    无
* @return        pdFAIL 发送失败 pdPASS 发送成功
* @attention     无
*******************************************************************************/
extern uint32_t net_free_send_data( uint16_t sock_id ,uint8_t * data , uint16_t len );

/** ****************************************************************************
* @remarks       int32_t  net_free_recv( uint16_t sock_id ,uint8_t * data , uint16_t len )
* @brief         接收 TCP 数据函数，一次读取最长不超过 2048 字节。
* @param[in]     sock 创建的sock id  
* @param[in]     len 接收数据 data 首地址 
* @param[out]    *data 数据首地址
* @return        ≥0 - 实际接收到的数据长度(对端正常断开为 0) ＜0 - socket 错误（网络异常断开-1）
* @attention     无
*******************************************************************************/
extern int32_t net_free_recv( uint16_t sock_id ,uint8_t * data , uint16_t len );

/** ****************************************************************************
* @remarks       uint32_t net_free_connect( char *ip, uint16_t port, uint8_t protocol_type, uint8_t *con_index, uint8_t *conn_staus, uint32_t *con_socketid , uint32_t ip_type)
* @brief         连接GPRS网络，无节点维护
* @param[in]    *ip IP地址 
* @param[in]     port 端口号 
* @param[in]     ip_type 连接类型
* @param[out]    *con_socketid 网络ID号
* @return        pdFAIL 链接失败 pdPASS 链接成功
* @attention     无
*******************************************************************************/
extern uint32_t net_free_connect( char *ip, uint16_t port, uint8_t protocol_type, uint32_t *con_socketid , uint32_t ip_type);

/** ****************************************************************************
* @remarks       uint32_t net_send_data_total_count_get( void )
* @brief         获取网络发送数据的总量
* @param[in]     index 网络节点
* @param[out]    无
* @return        网络发送数据包总个数，单位 byte
* @attention     无
*******************************************************************************/
extern uint32_t net_send_data_total_count_get( uint8_t index );

/** ****************************************************************************
* @remarks       uint32_t net_recv_data_total_count_get( void )
* @brief         获取网络接收数据的总量
* @param[in]     index 网络节点 
* @param[out]    无
* @return        网络接收数据包总个数，单位 byte
* @attention     无
*******************************************************************************/
extern uint32_t net_recv_data_total_count_get( uint8_t index );

/** ****************************************************************************
* @remarks       uint32_t net_dns_ip_addr_get( char *dns, char *get_ip )
* @brief         获取域名IP地址
* @param[in]     *dns 域名地址
* @param[out]    *get_ip 解析后的IP地址
* @return        pdFAIL 失败，pdPASS 成功
* @attention     无
*******************************************************************************/
extern uint32_t net_dns_ip_addr_get( char *dns, char *get_ip );

/** ****************************************************************************
* @remarks       uint32_t net_connection_status_get( uint8_t index )
* @brief         获取网络的连接状态
* @param[in]     index 网络节点
* @param[out]    无
* @return        pdPASS 网络连接成功，pdFAIL 网络连接失败
* @attention     无
*******************************************************************************/
extern uint32_t net_connection_status_get( uint8_t index );

#endif

